package org.nice.in.json;

import org.json.JSONArray;
import org.json.JSONException;

/**
 * Represents a nice JSONArray - nice in that it does not throw exceptions, and
 * makes accessing specific fields of nested objects; similar to ResultSet, a
 * NiceJSONArray has an internal counter that can be used to access elements, one
 * by one, using the first() and next() methods.
 * @since 6/14/2011
 * @version 1.0
 * @author katie
 * @param <T> 
 */
public class NiceJSONArray<T> {

    private JSONArray list;
    private int cur;

    /**
     * Initialized internal counter to zero and stores a reference to the given
     * JSONArray object.
     * @param list This will be the main source data wrapped by this class; if
     * this is null, most things will fail, ungracefully... but that's why this is not public!
     */
    protected NiceJSONArray(JSONArray list) {
        this.list = list;
        this.cur = 0;
    }

    /**
     * Returns if there is nothing in the underlying list.
     * @return 
     */
    public boolean isEmpty() {
        return size() == 0;
    }

    /**
     * Resets internal element counter to zero, and returns whether the array has anything in it.
     * @return false iff list is empty - equivalent to isEmpty()
     */
    public boolean first(){
        this.cur = 0;
        return isEmpty();
    }
    
    /**
     * Moves the internal counter along to the next element, if possible (not possible when reach the end).
     * @return  true iff there are more elements in the list remaining.
     */
    public boolean next() {
        if (cur < list.length() - 1) {
            cur++;
            return true;
        }
        return false;
    }

    /**
     * 
     * @param path
     * @param pathDelim
     * @return 
     */
    public T get(NiceJSONPath path) {
        return (T) path.getObjectFromArray(list,cur);
    }

    public int[] getIntArray(NiceJSONPath path) {
        return (new NiceJSONArray((JSONArray) get(path))).toIntArray();
    }

    public double[] getDoubleArray(NiceJSONPath path) {
        return (new NiceJSONArray((JSONArray) get(path))).toDoubleArray();
    }

    public String[] getStringArray(NiceJSONPath path) {
        return (new NiceJSONArray((JSONArray) get(path))).toStringArray();
    }

    public int[] toIntArray() {
        int[] out = new int[list.length()];
        for (int i = 0; i < out.length; i++) {
            try {
                out[i] = list.getInt(i);
            } catch (JSONException ex) {
                System.out.println(i + "th int element not read!");
            }
        }
        return out;
    }

    public double[] toDoubleArray() {
        double[] out = new double[list.length()];
        for (int i = 0; i < out.length; i++) {
            try {
                out[i] = list.getDouble(i);
            } catch (JSONException ex) {
                System.out.println(i + "th double element not read!");
            }
        }
        return out;
    }

    public String[] toStringArray() {
        String[] out = new String[list.length()];
        for (int i = 0; i < out.length; i++) {
            try {
                out[i] = list.getString(i);
            } catch (JSONException ex) {
                System.out.println(i + "th string element not read!");
            }
        }
        return out;
    }

    public int size() {
        return list.length();
    }

    public static NiceJSONArray getList(String feed, NiceJSONPath path) {
            return new NiceJSONArray((JSONArray)path.getObject(feed));
    }


}
